#include <Connectivity/TCPConnection.hpp>

TCPConnection::TCPConnection(int sock, struct sockaddr *socketaddr) {

	this->sock = sock;
	this->socketaddr = socketaddr;
	this->connected = true;

	this->sendFlags = 0;
	this->recvFlags = 0;

	fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);

}

TCPConnection::~TCPConnection(){
	closeConnection();
}

int TCPConnection::sendData(void *data, size_t len) {

	if (connected) {

		size_t sendCount = 0;

		while (sendCount < len) {

			int returnCode = send(sock, (char*)data + sendCount, len - sendCount, sendFlags); //MSG_NOSIGNAL);


			if (returnCode > -1) {
				sendCount += returnCode;
			} else {
				closeConnection();
				break;
			}
		}

		return sendCount;
	}

	return -1;

}

int TCPConnection::receiveData(void *data, size_t len) {

	if (connected) {

		size_t recvCount = 0;

		while (recvCount < len) {

			errno = 0;
			int returnCode = recv(sock, (char*)data + recvCount, len - recvCount, recvFlags); //MSG_WAITALL);

			switch(errno){
			case 0:
				if(returnCode > 0){
					recvCount += returnCode;
				}else{
					return -1;
				}
				break;
			case EWOULDBLOCK:
				return recvCount;
				break;
			default:
				closeConnection();
				return -1;
				break;


			}

		}
		return recvCount;
	}

	return -1;

}

void TCPConnection::getHostname(std::string &hostname){

	struct sockaddr_in6 *socketaddr6 = (struct sockaddr_in6*)socketaddr;

	char ipv6Address[INET6_ADDRSTRLEN];
	inet_ntop(AF_INET6, &socketaddr6->sin6_addr, ipv6Address, sizeof(ipv6Address));
	hostname.assign(ipv6Address);

}

int TCPConnection::getPort(){

	sockaddr_in6 *ipv6In = (sockaddr_in6*)socketaddr;

	return ipv6In->sin6_port;

}


bool TCPConnection::isConnected() {
	return connected;
}

void TCPConnection::closeConnection() {
	close(sock);
	connected = false;
}

void TCPConnection::setSendFlags(int sendFlags){
	this->sendFlags = sendFlags;
}

int TCPConnection::getSendFlags(){
	return sendFlags;
}

void TCPConnection::setRecvFlags(int recvFlags){
	this->recvFlags = recvFlags;
}

int TCPConnection::getRecvFlags(){
	return recvFlags;
}

int TCPConnection::getSock(){
	return sock;
}
